import logging

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
from starlette import status
from starlette.requests import Request

from src.core.exceptions.common import AppException

from ...core.exceptions.user import UserPhoneNotExist, UserTgIdNotExist
from .responses.exceptions import ErrorResult

logger = logging.getLogger(__name__)


def setup_exception_handlers(app: FastAPI) -> None:
    app.add_exception_handler(UserTgIdNotExist, user_tg_id_not_exist_handler)
    app.add_exception_handler(UserPhoneNotExist, user_phone_not_exist_handler)
    app.add_exception_handler(Exception, unknown_exception_handler)


async def user_tg_id_not_exist_handler(
    request: Request, err: UserTgIdNotExist
) -> ORJSONResponse:
    return await handle_error(request, err, status_code=status.HTTP_404_NOT_FOUND)


async def user_phone_not_exist_handler(
    request: Request, err: UserPhoneNotExist
) -> ORJSONResponse:
    return await handle_error(request, err, status_code=status.HTTP_404_NOT_FOUND)


async def unknown_exception_handler(_, err: Exception) -> ORJSONResponse:
    logger.error("Handle error", exc_info=err, extra={"error": err})
    logger.exception("Unknown error occurred", exc_info=err, extra={"error": err})
    return ORJSONResponse(
        ErrorResult(message="Unknown server error has occurred", data=err),
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
    )


async def handle_error(
    request: Request, err: AppException, status_code: int
) -> ORJSONResponse:
    logger.error("Handle error", exc_info=err, extra={"error": err})
    return ORJSONResponse(
        ErrorResult(message=err.message, data=err),
        status_code=status_code,
    )
